/*
 * @Author: jianfanfan 1217572833@qq.com
 * @Date: 2025-03-19 17:33:25
 * @LastEditors: jianfanfan 1217572833@qq.com
 * @LastEditTime: 2025-04-24 19:57:14
 * @FilePath: \guozaoke\src\node\post.service.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { Injectable, NotFoundException, HttpStatus } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Post } from './entities/post.entity';
import { Node } from './entities/node.entity';
import { Reply } from './entities/reply.entity';
import { CreateReplyDto } from './dto/create-reply.dto';
import { CreatePostDto } from './dto/create-post.dto';
import { UpdatePostDto } from './dto/update-post.dto';
import { User } from '../auth/entities/user.entity';
import { JwtService } from '@nestjs/jwt';
import { CacheService } from '../common/services/cache.service';
import {
  optimizePostsData,
  formatDate,
  extractAuthorData,
} from '../common/utils/data-transformer.util';

@Injectable()
export class PostsService {
  constructor(
    @InjectRepository(Post)
    private readonly postRepository: Repository<Post>,
    @InjectRepository(Node)
    private readonly nodeRepository: Repository<Node>,
    @InjectRepository(Reply)
    private readonly replyRepository: Repository<Reply>,
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    private readonly jwtService: JwtService,
    private readonly cacheService: CacheService,
  ) {}

  async createReply(createReplyDto: CreateReplyDto, token: string) {
    // 创建回复时清除相关缓存
    await this.cacheService.del(`post:${createReplyDto.postId}:replies`);
    const decoded = this.jwtService.verify(token);
    const user = await this.userRepository.findOne({
      where: { id: decoded.sub },
    });

    if (!user) {
      throw new NotFoundException('用户不存在');
    }
    const post = await this.postRepository.findOne({
      where: { id: createReplyDto.postId },
    });

    if (!post) {
      throw new NotFoundException('帖子不存在');
    }

    const reply = this.replyRepository.create({
      content: createReplyDto.content,
      post,
      author: user,
    });

    return this.replyRepository.save(reply);
  }

  // 创建文章
  async createPost(createPostDto: CreatePostDto, token: string): Promise<any> {
    // 创建帖子时清除相关缓存
    await this.cacheService.del('posts:all');
    await this.cacheService.del(`posts:node:${createPostDto.nodeId}`);
    await this.cacheService.del(`node:${createPostDto.nodeId}:posts`);
    const decoded = this.jwtService.verify(token);
    const node = await this.nodeRepository.findOne({
      where: { id: createPostDto.nodeId },
    });

    if (!node) {
      throw new NotFoundException('节点不存在');
    }

    const post = new Post();
    post.title = createPostDto.title;
    post.content = createPostDto.content;
    post.node = node;
    post.author = decoded.sub;
    await this.postRepository.save(post);
    return {
      code: HttpStatus.CREATED,
      message: '创建成功',
    };
  }

  // 获取所有帖子
  async findAllPosts(): Promise<any> {
    const cacheKey = 'posts:all';

    return await this.cacheService.getOrSet(
      cacheKey,
      async () => {
        const posts = await this.postRepository.find({
          relations: ['author', 'node'],
          order: { createTime: 'DESC' },
        });

        // 优化返回的帖子数据 - 处理内容和格式化日期
        const optimizedPosts = optimizePostsData(posts, true, true);

        return {
          code: HttpStatus.OK,
          data: optimizedPosts,
        };
      },
      600,
    ); // 缓存10分钟
  }

  // 获取节点下的帖子列表
  async findPostsByNode(nodeId: number): Promise<any> {
    const cacheKey = `posts:node:${nodeId}`;

    return await this.cacheService.getOrSet(
      cacheKey,
      async () => {
        const posts = await this.postRepository.find({
          where: { node: { id: nodeId } },
          relations: ['author', 'node'],
          order: { createTime: 'DESC' },
        });

        // 优化返回的帖子数据 - 处理内容和格式化日期
        const optimizedPosts = optimizePostsData(posts, true, true);

        return {
          code: HttpStatus.OK,
          data: optimizedPosts,
        };
      },
      600,
    ); // 缓存10分钟
  }

  //获取帖子详情
  async findPostById(postId: number): Promise<any> {
    const cacheKey = `post:${postId}`;

    // 帖子详情不使用getOrSet方法，因为需要更新浏览量
    const cachedPost = await this.cacheService.get(cacheKey);
    if (cachedPost) {
      return cachedPost;
    }

    const post = await this.postRepository.findOne({
      where: { id: postId },
      relations: ['author', 'node'],
    });

    if (!post) {
      return {
        code: HttpStatus.NOT_FOUND,
        message: '帖子不存在',
      };
    }

    post.views++;
    await this.postRepository.save(post);

    // 帖子详情不需要处理内容，但需要格式化日期
    // 使用详细的日期时间格式
    const optimizedPost = optimizePostsData([post], false, false)[0];

    // 格式化日期字段
    const result = {
      code: HttpStatus.OK,
      data: {
        ...optimizedPost,
        createTime: formatDate(post.createTime, 'YYYY-MM-DD HH:mm:ss'),
        updateTime: formatDate(post.updateTime, 'YYYY-MM-DD HH:mm:ss'),
      },
    };

    // 缓存帖子详情，但时间较短
    await this.cacheService.set(cacheKey, result, 300); // 缓存5分钟

    return result;
  }

  // 更新帖子
  async updatePost(
    id: number,
    updatePostDto: UpdatePostDto,
    token: string,
  ): Promise<any> {
    // 更新帖子时清除相关缓存
    await this.cacheService.del(`post:${id}`);
    await this.cacheService.del('posts:all');
    try {
      const decoded = this.jwtService.verify(token);
      const post = await this.postRepository.findOne({
        where: { id },
        relations: ['author'],
      });

      if (!post) {
        return {
          code: HttpStatus.NOT_FOUND,
          message: '帖子不存在',
        };
      }

      if (post.author.id !== decoded.sub) {
        return {
          code: HttpStatus.FORBIDDEN,
          message: '无权修改此帖子',
        };
      }

      // 更新帖子内容
      if (updatePostDto.title) post.title = updatePostDto.title;
      if (updatePostDto.content) post.content = updatePostDto.content;

      await this.postRepository.save(post);
      return {
        code: HttpStatus.OK,
        message: '帖子更新成功',
      };
    } catch (error) {
      return {
        code: HttpStatus.UNAUTHORIZED,
        message: 'token无效或已过期',
      };
    }
  }

  // 删除帖子
  async deletePost(id: number, token: string): Promise<any> {
    // 获取帖子信息，用于后续清除缓存
    const post = await this.postRepository.findOne({
      where: { id },
      relations: ['node'],
    });

    if (post) {
      // 删除帖子时清除相关缓存
      await this.cacheService.del(`post:${id}`);
      await this.cacheService.del(`post:${id}:replies`);
      await this.cacheService.del('posts:all');
      if (post.node) {
        await this.cacheService.del(`posts:node:${post.node.id}`);
        await this.cacheService.del(`node:${post.node.id}:posts`);
      }
    }
    try {
      const decoded = this.jwtService.verify(token);
      const post = await this.postRepository.findOne({
        where: { id },
        relations: ['author'],
      });

      if (!post) {
        return {
          code: HttpStatus.NOT_FOUND,
          message: '帖子不存在',
        };
      }

      if (post.author.id !== decoded.sub) {
        return {
          code: HttpStatus.FORBIDDEN,
          message: '无权删除此帖子',
        };
      }

      await this.postRepository.remove(post);
      return {
        code: HttpStatus.OK,
        message: '帖子已删除',
      };
    } catch (error) {
      return {
        code: HttpStatus.UNAUTHORIZED,
        message: 'token无效或已过期',
      };
    }
  }

  // 查找帖子的回复
  async findRepliesByPost(postId: number): Promise<any> {
    const cacheKey = `post:${postId}:replies`;

    return await this.cacheService.getOrSet(
      cacheKey,
      async () => {
        const post = await this.postRepository.findOne({
          where: { id: postId },
        });

        if (!post) {
          return {
            code: HttpStatus.NOT_FOUND,
            message: '帖子不存在',
          };
        }

        const replies = await this.replyRepository.find({
          where: { post: { id: postId } },
          relations: ['author'],
          order: { createTime: 'ASC' },
        });

        // 格式化回复日期并精简数据
        const formattedReplies = replies.map((reply) => ({
          id: reply.id,
          content: reply.content,
          createdAt: formatDate(reply.createTime, 'YYYY-MM-DD HH:mm'),
          author: extractAuthorData(reply.author),
        }));

        return {
          code: HttpStatus.OK,
          data: formattedReplies,
        };
      },
      300,
    ); // 缓存5分钟
  }
}
